package hu.rsc.forbiddenwords.client.gui.application;

import hu.rsc.forbiddenwords.client.Forbiddenwords;
import hu.rsc.forbiddenwords.client.util.Logger;
import hu.rsc.forbiddenwords.client.util.SimpleCallback;
import hu.rsc.forbiddenwords.shared.ApplicationDTO;
import hu.rsc.forbiddenwords.shared.LanguageDTO;

import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;

public class ApplicationForm extends Composite {
    private ApplicationPanel parent;

    private FlexTable form = new FlexTable();

    private List<LanguageDTO> availableLanguages;

    private TextBox nameTb;
    private ListBox langLb;
    private CheckBox openedCb;
    Button save = new Button();

    private ApplicationDTO entry = new ApplicationDTO(0l);

    public ApplicationForm(ApplicationPanel parent) {
	this.parent = parent;
	buildContent();
	initWidget(this.form);
    }

    public ApplicationDTO getEntry() {
	return this.entry;
    }

    public LanguageDTO getSelectedLanguage() {
	try {
	    Long id = Long.parseLong(this.langLb.getValue(this.langLb.getSelectedIndex()));
	    int index = this.availableLanguages.indexOf(new LanguageDTO(id));
	    return this.availableLanguages.get(index);
	} catch (Exception e) {
	    return null;
	}
    }

    public void refresh(ApplicationDTO entry) {
	this.entry = entry;
	buildContent();
    }

    private void buildContent() {
	this.form.clear();
	this.form.addStyleName("form");
	this.form.addStyleName("border");
	int row = 0;

	Label lb = new Label("Applications");
	lb.addStyleName("BoldLabel");
	this.form.setWidget(row, 0, lb);
	this.form.getFlexCellFormatter().setColSpan(row, 0, 2);
	this.form.getFlexCellFormatter().setHorizontalAlignment(row, 0, HasHorizontalAlignment.ALIGN_CENTER);
	row++;

	lb = new Label();
	lb.addStyleName("formlabel");
	lb.setText("name");
	this.form.setWidget(row, 0, lb);
	this.nameTb = new TextBox();
	this.nameTb.addStyleName("forminput");
	this.form.setWidget(row, 1, this.nameTb);
	this.nameTb.setValue(this.entry.getName());
	row++;

	lb = new Label();
	lb.addStyleName("formlabel");
	lb.setText("language");
	this.form.setWidget(row, 0, lb);
	this.langLb = new ListBox();
	this.langLb.addStyleName("forminput");
	this.form.setWidget(row, 1, this.langLb);
	getLanguages();
	row++;

	lb = new Label();
	lb.addStyleName("formlabel");
	lb.setText("public");
	this.form.setWidget(row, 0, lb);
	this.openedCb = new CheckBox();
	this.openedCb.addStyleName("forminput");
	this.form.setWidget(row, 1, this.openedCb);
	this.openedCb.setValue(this.entry.isOpened());
	row++;

	HorizontalPanel buttonPanel = new HorizontalPanel();
	buttonPanel.addStyleName("buttonpanel");
	this.form.setWidget(row, 0, buttonPanel);
	this.form.getFlexCellFormatter().setColSpan(row, 0, 2);

	this.save.setText("Save");
	buttonPanel.add(this.save);

	this.save.addClickHandler(new ClickHandler() {

	    @Override
	    public void onClick(ClickEvent event) {
		if (validate()) {
		    ApplicationForm.this.parent.save(ApplicationForm.this.entry);
		}
	    }
	});

	Button newBt = new Button();
	newBt.setText("New");
	buttonPanel.add(newBt);
	newBt.addClickHandler(new ClickHandler() {

	    @Override
	    public void onClick(ClickEvent event) {
		refresh(new ApplicationDTO(0l));
	    }
	});
	setEditable();
    }

    private void getLanguages() {
	Forbiddenwords.getService().getLanguages(new SimpleCallback<List<LanguageDTO>>() {

	    @Override
	    public void onSuccess(List<LanguageDTO> result) {
		initLanguages(result);
	    }
	});
    }

    private void initLanguages(List<LanguageDTO> langs) {
	this.availableLanguages = langs;
	this.langLb.addItem("", "-1");
	for (int i = 0; i < langs.size(); i++) {
	    LanguageDTO lang = langs.get(i);
	    this.langLb.addItem(lang.getName(), lang.getId().toString());
	    if (this.entry.getLanguage() != null && this.entry.getLanguage().equals(lang.getCode())) {
		this.langLb.setSelectedIndex(i + 1);
	    }
	}
    }

    private void setEditable() {
	this.langLb.setEnabled(this.entry.isEditable());
	this.nameTb.setEnabled(this.entry.isEditable());
	this.openedCb.setEnabled(this.entry.isEditable());
	this.save.setEnabled(this.entry.isEditable());
    }

    private boolean validate() {
	this.entry.setName(this.nameTb.getValue());
	LanguageDTO lang = getSelectedLanguage();
	if (lang != null) {
	    this.entry.setLanguage(lang.getCode());
	} else {
	    this.entry.setLanguage(null);
	}
	this.entry.setOpened(this.openedCb.getValue());

	StringBuilder error = new StringBuilder();
	if (this.entry.getName() == null || this.entry.getName().length() == 0) {
	    error.append("The name is empty.");
	}

	if (this.entry.getLanguage() == null || this.entry.getLanguage().length() == 0) {
	    error.append("The language is empty.");
	}

	if (error.length() > 0) {
	    Logger.logError(error.toString());
	    return false;
	}
	return true;
    }
}
